﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

#pragma once

#include "GcmpModelInterface.h"
#include "IExternalObject.h"
#include "NdbDataSchema.h"
#include "GbmpQuickCast.h"
#include "ElementCreationOptions.h"
#include "IGraphicsText.h"
#include "IGraphicsElementShape.h"
#include "IDrawingTableItem.h"
#include "GcmpApiDeclaration.h"

namespace gcmp
{
    class IDocument;
    class IDrawingTableEvent;
    class IExternalDatas;

    /// \brief 图形化表格Element对象
    class GCMP_MODEL_INTERFACE_EXPORT IDrawingTable : public IExternalObject
    {
        DEFINE_CAST_DERIVED(IDrawingTable, gcmp::IExternalObject);
    public:
        virtual ~IDrawingTable();
    public:
        /// \brief 获取所属Document
        ///
        /// \return IDocument* 所属Element
        virtual const IDocument* GetDocument() const = 0;

        /// \brief 设置所属ModelView的ID
        ///
        /// \return ElementId 所属Element
        virtual const ElementId GetModelViewId() const = 0;
    public:
        /// \brief 获取DrawingTable的所有外部扩展数据
        ///
        /// \return 返回DrawingTable的所有外部扩展数据
        virtual const IExternalDatas* GetExternalDatas() const = 0;

        /// \brief 获取DrawingTable的所有外部扩展数据，用户可以通过此返回值对外部扩展数据进行修改
        ///
        /// \return 返回DrawingTable的所有外部扩展数据
        virtual IExternalDatas* GetExternalDatas() = 0;
        /// \brief 是否为空表（没有任何行或者列）
        ///
        /// \return true 空, false 非空
        virtual bool IsEmpty() const = 0;
        /// \brief 横向、竖向表格判断
        ///
        /// \return true 表示横向, false 表示竖向
        virtual bool IsHorizontalTable() const = 0;

        /// \brief 设置表格描述信息
        ///
        /// \param description 描述信息
        virtual void SetDescription(const std::wstring &description) = 0;

        /// \brief 获取表格描述信息
        ///
        /// \return wstring 描述信息
        virtual const std::wstring& GetDescription() const = 0;

        /// \brief 设置表格自定义比例
        ///
        /// \param dScale 比例值(>=1.0)
        virtual void SetScale(double dScale) = 0;

        /// \brief 获取自定义比例
        ///
        /// \return double 比例值
        virtual double GetScale() const = 0;


        /// \brief 设置表头的行或者列数量
        /// 
        /// \param nQuantity 表头行或者列数量(横表为行数，竖表为列数)
        /// \return bool ture成功 false失败
        virtual bool SetHeaderQuantity(Int16 nQuantity) = 0;

        /// \brief 获取表头行或者列数量
        ///
        /// \return Int16 表头的行或者列数量
        virtual Int16 GetHeaderQuantity() const = 0;

        /// \brief 获取表格的坐标系
        ///
        /// \return Coordinate3d 坐标系
        virtual Coordinate3d GetCoordinate3d() const = 0;

        /// \brief 设置分页表的左上角位置
        ///
        /// \param pos 位置坐标
        /// \param nPage 分页表格索引
        virtual void SetPosition(const Vector3d &position, Int16 nPage) = 0;

        /// \brief 获取分页表的左上角位置
        ///
        /// \param nPage 分页表格索引
        /// \return Vector3d 分页表的左上角位置
        virtual Vector3d GetPosition(Int16 nPage) const = 0;

        /// \brief 获取分页表格的高度
        ///
        /// \param nPage 分页表格索引
        /// \return double 分页表的高度
        virtual double GetHeight(Int16 nPage) const = 0;

        /// \brief 获取分页表格的宽度
        ///
        /// \param nPage 分页表格索引
        /// \return double 分页表的宽度
        virtual double GetWidth(Int16 nPage) const = 0;

        /// \brief 设置分页表可容纳的行数量
        ///
        /// \param nCount 行数量
        /// \return bool ture成功  false失败
        virtual bool SetPerPageCount(Int16 nCount) = 0;

        /// \brief 获取分页表可容纳的行数量
        ///
        /// \return int 分页可容纳的行数量
        virtual Int16 GetPerPageCount() const = 0;

        /// \brief 设置表格文字方向
        ///
        /// TextDirection 左到右，右到左，下到上， 上到下
        /// \param txtDirection 文字方向
        virtual void SetTextDirection(TextDirection txtDirection) = 0;

        /// \brief 获取表格文字方向
        ///
        /// \return TextDirection 文字方向
        virtual TextDirection GetTextDirection() const = 0;

        /// \brief 设置表格的行高
        ///
        /// 如果oIndex为默认值，则会调整所有行的行高为统一值
        /// \param dValue 行高值
        /// \param oIndex 指定行的索引(如果m_nPage<0或者m_nRow<0，则所有行高均做调整)
        /// \param bAdjustPosition ture 调整表格左上位置  false不调整
        /// \调整距离会根据新旧值计算偏移向量，一般来说单元格上侧夹点拖拽需要设为ture，下侧夹点则设为fasle
        virtual void SetRowHeight(double dValue, const TableItemIndex &oIndex, bool bAdjustPosition = false) = 0;

        /// \brief 设置表格的行高
        ///
        /// 如果oIndex为默认值，则会调整所有行的行高为统一值
        /// \param dValue 行高值
        /// \param nType  指定类型（-1：所有行  0：表头行  1：正文行）
        virtual void SetRowHeight(double dValue, int nType = -1) = 0;

        /// \brief 获取表格的行高
        ///
        /// 如果oIndex为默认值，则会返回表格默认行高
        /// oIndex有效的时候，先通过oIndex对应的单元格对象（GetTableItem(oIndex)可获取），再通过IDrawingTableItem::GetHeight()高度值效果一致。
        /// 使用可参照https://km.glodon.com/pages/viewpage.action?pageId=379559666
        /// \param oIndex 指定行的索引
        /// \return double 行高值
        virtual double GetRowHeight(const TableItemIndex &oIndex) const = 0;
     
        /// \brief 获取表格指定行的最小许可高度
        ///
        /// 如果oIndex为默认值，则会返回一个字的字高
        /// 依赖于IDrawingTableMinimumSizeManager设置的最小值（该值由产品决定），不会比这个值更小
        /// \param oIndex 指定行的索引
        /// \return double 最小行高值（根据文字内容计算高度值）
        virtual double GetRowMinimumAllowedHeight(const TableItemIndex &oIndex) const = 0;

        /// \brief 设置表格的列宽
        ///
        /// 如果oIndex为默认值，则会调整所有行的列宽为统一值
        /// \param dValue 列宽值
        /// \param oIndex 指定列的索引(如果m_nPage<0或者m_nCol<0，则所有列宽均做调整)
        /// \param bAdjustPosition ture 调整表格左上位置  false不调整
        /// \调整距离会根据新旧值计算偏移向量，一般来说单元格左侧夹点拖拽需要设为ture，右侧夹点则设为fasle
        virtual void SetColumnWidth(double dValue, const TableItemIndex &oIndex, bool bAdjustPosition = false) = 0;

        /// \brief 设置表格的列宽
        ///
        /// 如果oIndex为默认值，则会调整所有行的行高为统一值
        /// \param dValue 列宽值
        /// \param nType  指定类型（-1：所有列  0：表头列  1：正文列）
        virtual void SetColumnWidth(double dValue, int nType = -1) = 0;

        /// \brief 获取表格指定列的最小许可宽
        ///
        /// 如果oIndex为默认值，则会返回一个字的字宽
        /// 依赖于IDrawingTableMinimumSizeManager设置的最小值(该值由产品决定)，不会比这个值更小
        /// \param oIndex 指定行的索引
        /// \return double 最小行宽度值
        virtual double GetColumnMinimumAllowedWidth(const TableItemIndex &oIndex) const = 0;

        /// \brief 获取表的格列宽
        ///
        /// 如果oIndex为默认值，则会返回表格默认列宽
        /// oIndex有效的时候，与通过oIndex对应的单元格对象（GetTableItem(oIndex)可获取）后通过IDrawingTableItem::GetWidth() 宽度值效果一致。
        /// 使用可参照https://km.glodon.com/pages/viewpage.action?pageId=379559666
        /// \param oIndex 指定列的索引
        /// \return double 列宽值
        virtual double GetColumnWidth(const TableItemIndex &oIndex) const = 0;

        /// \brief 在指定位置向前插入任意空行
        ///
        /// 适配老接口有两种方式
        /// 1、传入的count值为0时，单元格插入行为跟AddRow()老接口一致
        /// 2、根据GetItemRange()获取复合单元格索引范围，根据复合单元格的行数作为count值传入
        /// 如果itemIndex中page为小于0则插入失败，如果Row为-1，则会在表格的末尾插入一行，否则按指定位置插入行
        /// \param itemIndex 指定行的索引
        /// \param count 插入的行数, count值不小于0
        /// return true 插入成功，false 插入失败
        virtual bool AddRows(const TableItemIndex& itemIndex, int count) = 0;

        /// \brief 删除表格指定行数据
        ///
        /// 当表格中所有行都被删除后，表格对象仍然存在，不会被自动删除，由用户通过IsEmpty()方法判断是否空表来决定是否删除表格element。
        /// \param oIndex 指定行的索引
        /// 如果删除的是表头行，则所有分页的对应表头行均会删除
        virtual bool DeleteRow(const TableItemIndex &oIndex) = 0;

        /// \brief 获取表格总行数
        ///
        /// \param nPage 分页表格索引
        /// \return Int16 总行数
        virtual Int16 GetRowCount(Int16 nPage) const = 0;

        /// \brief 在指定位置向前插入任意空列
        /// 
        /// 适配老接口有两种方式
        /// 1、传入的count值为0时，单元格插入行为跟AddColumn()老接口一致
        /// 2、根据GetItemRange()获取复合单元格索引范围，根据复合单元格的列数作为count值传入
        /// 如果itemIndex中page小于0则插入失败，如果Col为-1，则会在表格的末尾插入一列，否则按指定位置插入列
        /// \param itemIndex 指定列的索引
        /// \param count 插入的列数，count值不小于0
        /// return true 插入成功，false 插入失败
        virtual bool AddColumns(const TableItemIndex& itemIndex, int count) = 0;

        /// \brief 删除表格指定列数据
        ///
        /// 当表格中所有列都被删除后，表格对象仍然存在，不会被自动删除，由用户通过IsEmpty()方法判断是否空表来决定是否删除表格element。
        /// \param oIndex 指定列的索引
        /// 如果删除的是表头列，则所有分页的对应表头列均会删除
        virtual bool DeleteColumn(const TableItemIndex &oIndex) = 0;

        /// \brief 获取单元格的(TableItemIndex)索引范围
        /// 
        /// 传入复合单元格任意itemIndex，获取到该复合单元格的索引范围
        /// 传入非复合单元格(itemIndex)则返回自身
        /// itemIndex中的page小于0，返回的vector为空
        /// \param itemIndex 单元格的索引位置
        /// \return std::vector<TableItemIndex> 返回单元格索引(TableItemIndex)范围
        virtual std::vector<TableItemIndex> GetItemRange(const TableItemIndex& itemIndex) const = 0;

        /// \brief 获取当前item位置行的最小拓扑包围盒
        ///
        /// 注1：行表的表头行是行表的多分页标识，不是唯一的，没有固定返回值
        /// 注2：获取行的包围盒范围时，返回值的Index列信息可以为任意值， 该值不影响最小行、最大行范围
        /// \param itemIndex 单元格的索引位置
        /// \return 返回值first中的m_nRow为最小行、m_nPage为最小行所在页，second中的m_nRow为最大行、m_nPage为最大行所在页
        virtual std::pair<TableItemIndex, TableItemIndex> GetItemsRowRange(const TableItemIndex& itemIndex) const = 0;

        /// \brief 获取当前item位置列的最小拓扑包围盒
        ///
        /// 注1：列表的表头列是列表的多分页标识，不是唯一的，也没有固定返回值
        /// 注2：获取列的包围盒范围时，返回值的Index行信息可以为任意值，该值不影响最小列、最大列范围
        /// \param itemIndex 单元格的索引位置
        /// \return 返回值first中的m_nCol为最小列、m_nPage为最小列所在页，second中的m_nCol为最大列、m_nPage为最大列所在页
        virtual std::pair<TableItemIndex, TableItemIndex> GetItemsColumnRange(const TableItemIndex& itemIndex) const = 0;

        /// \brief 获取表格总列数
        ///
        /// \param nPage 分页表格索引
        /// \return Int16 总列数
        virtual Int16 GetColumnCount(Int16 nPage) const = 0;

        /// \brief 根据指定位置所对应的表格单元格索引
        ///
        /// \param point 坐标位置
        /// \return TableItemIndex 单元格对应索引
        virtual TableItemIndex GetItemIndexByPosition(const Vector3d &position) const = 0;

        /// \brief 合并若干个单元格
        ///
        /// 1. 需要传入若干单元格中的最小索引和最大索引，然后会合并从最小索引到最大索引所包含的所有单元格
        /// 2. 若其中有单元格被合并过，则不能再合并
        /// 3. 若其中既包含表头又包含非表头，则不能合并
        /// 4. 若其中的单元格不在同一页，则不支持合并
        /// \param minItemIndex 最小索引
        /// \param maxItemIndex 最大索引
        /// \param pErrorMessage 合并失败情况下，输出错误信息
        /// \return bool  ture合并成功  false合并失败
        virtual bool MergeTableItems(const TableItemIndex& minItemIndex, const TableItemIndex& maxItemIndex, std::wstring* pErrorMessage) = 0;

        /// \brief 恢复（合并反向操作）当前被选中的单元格
        ///
        /// \param itemIndex 需要取消合并的单元格索引
        /// \return bool  ture恢复成功  false恢复失败
        virtual bool RestoreTableItem(const TableItemIndex &itemIndex) = 0;

        /// \brief 根据索引值返回对应表格的单元格对象
        ///
        /// \param oIndex 单元格对应索引
        /// \return IDrawingTableItem 单元格对象
        virtual const IDrawingTableItem* GetTableItem(const TableItemIndex &oIndex) const = 0;

        /// \brief 根据索引值返回对应表格的单元格对象
        ///
        /// \param oIndex 单元格对应索引
        /// \return IDrawingTableItem 单元格对象(可写)
        virtual IDrawingTableItem* GetTableItemFW(const TableItemIndex &oIndex) = 0;

        /// \brief 根据item对应的ElementID返回索引
        ///
        /// \param oEntId item对应的ElementID
        /// \return TableItemIndex 单元格索引
        virtual TableItemIndex GetItemIndexByElementId(const ElementId &elementId) const = 0;

        /// \brief 获取分页表格数量
        ///
        /// \return Int16 表格数量
        virtual Int16 GetPageCount() const = 0;

        /// \brief 获取所有单元格关联的图例ID
        ///
        /// \return std::set<ElementId> 图例ID列表
        virtual std::set<ElementId> GetRelatedElementIds() const = 0;

        /// \brief 获取表中所有的单元格的ElementId
        ///
        /// \return std::set<ElementId>  表中所有的单元格的ElementId
        virtual std::set<ElementId>  GetTableItemIds() const = 0;

        /// \brief 批量设置指定单元格文字样式(内部遍历设置每个单元格文字样式)
        ///
        /// \param textStyle 文字样式
        /// \param indexs 指定单元格索引（如果为空则设置所有单元格文字样式）
        virtual void SetTextStyle(const TableTextStyle &textStyle, const std::set<TableItemIndex> &indexs) = 0;

        /// \brief 批量设置表头或者正文的文字样式
        ///
        /// \param textStyle 文字样式
        /// \param bHeaderOrBody true表示表头  false表示正文
        virtual void SetTextStyle(const TableTextStyle &textStyle, bool bHeaderOrBody) = 0;

        /// \brief 批量设置指定单元格边线样式
        ///
        /// \param styleId 样式id
        /// \param indexs 指定单元格索引（如果为空则设置所有单元格边线样式）
        virtual void SetItemOutlineStyleId(const ElementId& styleId, const std::set<TableItemIndex> &indexs) = 0;

        /// \brief 批量设置表头或者正文的单元格边线样式
        ///
        /// \param styleId 样式id
        /// \param bHeaderOrBody true表示表头  false表示正文
        virtual void SetItemOutlineStyleId(const ElementId& styleId, bool bHeaderOrBody) = 0;

        /// \brief 设置指定范围的外围边框线样式
        ///
        /// \param styleId 样式id
        /// \param minIndex 范围内索引最小值
        /// \param maxIndex 范围内索引最大值
        /// \最大和最小索引，必须保证在同一分页内，也就是就是m_nPage必须相同
        virtual void SetSpecifiedRangeOutlineStyleId(const ElementId& styleId, const TableItemIndex& minIndex, const TableItemIndex& maxIndex) = 0;
    
        /// \brief 锁定表格分页
        ///
        /// \按照表格分页间距重置表格分页位置，
        /// \调整列宽或者行高时，各分页会保持相应间距，避免重叠
        /// \各分页的左上角夹点作用，均为移动整表
        virtual void LockTablePage() = 0;

        /// \brief 取消表格分页锁定
        ///
        /// \各分页位置保持不变
        /// \调整列宽或者行高时，各分页位置不变，会存在重叠
        /// \各分页的左上角夹点作用，除首页为移动整表，其余为移动各分表
        virtual void UnlockTablePage() = 0;

        /// \brief 判断表格是是否锁定
        ///
        /// \return bool  true锁定  false未锁定
        virtual bool IsTablePageLocked() const = 0;

        /// \brief 设置表格分页之间的间距
        ///
        /// \param dSpace 分页间距值（>=0, 如果小于0，则强制为0）
        virtual void SetTablePageSpace(double dSpace) = 0;

        /// \brief 获取表格分页之间的间距
        ///
        /// \return double  分页间距
        virtual double GetTablePageSpace() const = 0;

        /// \brief 交换指定的行或者列对象
        ///
        /// \param oIndex1   需要交换的列或者列索引
        /// \param oIndex2   需要交换的列或者列索引
        /// \param bRowOrColumn  ture表示交换行  false表示交换列
        /// \说明：表头行列与表头行列不能互换，表头行列与数据行列不能互换
        /// \return bool  true成功  false失败
        virtual bool exchangeRowOrColumn(const TableItemIndex &oIndex1, const TableItemIndex &oIndex2, bool bRowOrColumn) = 0;
        /// \brief 设置单元格最小高度
        ///
        /// \param oIndex 单元格索引
        /// \param dValue 高度值
        /// \return bool  true成功  false失败
        virtual bool SetItemMinimumHeight(const TableItemIndex &oIndex, double dValue) = 0;

        /// \brief 设置单元格最小宽度
        ///
        /// \param oIndex 单元格索引
        /// \param dValue 宽度值
        /// \return bool  true成功  false失败
        virtual bool SetItemMinimumWidth(const TableItemIndex &oIndex, double dValue) = 0;

        /// \brief 是否允许单元格末行留白
        ///
        /// \param bNeedBlank true留白 false不留白
        virtual void SetIsNeedBlankByTextWrap(bool bNeedBlank) = 0;

        /// \brief 单元格末行是否留白
        ///
        /// \return bool  true留白 false不留白
        virtual bool IsNeedBlankByTextWrap() const = 0;

        /// \brief 设置表格默认样式是否智能反色
        ///
        /// \说明：
        /// \   1)这里说的是表格自身默认样式，用户设置的样式由用户自用控制
        /// \   2)此接口会用表格的默认样式重置一次文字及边线样式
        /// \param bSmartColorMode true智能反色 false非智能反色
        virtual void SetDefaultSmartColor(bool bSmartColorMode) = 0;

        /// \brief 获取表格默认样式是否智能反色
        ///
        /// \return bool  true智能反色 false非智能反色
        virtual bool IsDefaultSmartColor() const = 0;

        /// \brief 设置是否生成表格的分页夹点
        ///
        /// 设置后，再次生成表格夹点时起效
        /// \param isNeedPageGripPoint 是否生成表格分页夹点
        /// \return true-设置成功，false-设置失败
        virtual bool SetIsNeedPageGripPoint(bool isNeedPageGripPoint) = 0;

        /// \brief 是否生成表格的分页夹点
        ///
        /// \return 返回是否生成表格分页夹点。true-生成表格分页夹点，false-不生成表格分页夹点
        virtual bool IsNeedPageGripPoint() const = 0;

        /// \brief 设置单元格边框线可见性
        ///
        /// \param itemIndex 单元格index
        /// \param isVisible 边线是否可见，true表示总是可见，false表示GraphicsNodeVisibility::HighlightedExactly_Or_SelectedExactly，高亮或选择可见
        /// \param lineType 单元格边线类型
        /// \return bool true 成功，否则失败
        virtual bool SetOutlineVisibility(const TableItemIndex& itemIndex, TableItemOutLineType lineType,bool isVisible) = 0;

        /// \brief 获取单元格边框线可见性
        ///
        /// \param itemIndex 单元格index
        /// \param lineType 单元格边线类型（若为TableItemOutLineType::All,返回值为4条边线是否都可见）
        /// \return bool 边线是否可见，true表示总是可见，false表示GraphicsNodeVisibility::HighlightedExactly_Or_SelectedExactly，高亮或选择可见
        virtual bool GetOutlineVisibility(const TableItemIndex& itemIndex, TableItemOutLineType lineType) const = 0;


        /// \brief 通过复合单元格内任一索引获取复合单元格主单元格索引(复合单元格内最小索引)
        ///
        /// \param mergedItemIndex 合单元格内任一Index，若mergedItemIndex为非复合单元格内索引，则返回无效ItemIndex
        /// \return TableItemIndex 复合单元格主单元格索引
        virtual TableItemIndex GetMainTableItemIndexByMergedItemIndex(const TableItemIndex& mergedItemIndex) const = 0;

        /// \brief 将连续多行或单行单元格移动到指定行之前
        /// 1. 横向表不支持移动表头；横向表不支持移动到表头之前
        /// 2. 所有传入参数需要指定哪页哪行
        /// 3. startItemRowIndex-endItemRowIndex至少是最小行包围盒，否则移动失败
        /// 4. 如果要移动到最后一行之后，resultItemRowIndex的行号可以设置为最后一行索引+1
        /// 5. 如果resultItemRowIndex指定的行和其前一行存在，则resultItemRowIndex指定的行不能与前一行有复合单元格，否则移动失败
        /// 6. resultItemRowIndex的行索引不能在startItemRowIndex-endItemRowIndex行索引内，否则移动失败
        ///
        /// \param startItemRowIndex 移动的起始行索引
        /// \param endItemRowIndex 移动的终止行索引
        /// \param resultItemRowIndex 移动的目标行索引（移动到目标行索引之前）
        /// \return true-移动成功，false-移动失败
        virtual bool MoveItemsRowIndex(TableItemIndex startItemRowIndex, TableItemIndex endItemRowIndex, TableItemIndex resultItemRowIndex) = 0;

        /// \brief 将连续多列或单列单元格移动到指定列之前
        /// 1. 竖向表不支持移动表头；竖向表不支持移动到表头之前
        /// 2. 所有传入参数需要指定哪页哪列
        /// 3. startItemColumnIndex-endItemColumnIndex至少是最小列包围盒，否则移动失败
        /// 4. 如果要移动到最后一列之后，resultItemColumnIndex的列号可以设置为最后一列索引+1
        /// 5. 如果resultItemColumnIndex指定的列与其前一列存在，则resultItemColumnIndex指定的列不能与其前一列有复合单元格，否则移动失败
        /// 6. resultItemColumnIndex的列索引不能在startItemColumnIndex-endItemColumnIndex列索引内，否则移动失败
        ///
        /// \param startItemColumnIndex 移动的起始列索引
        /// \param endItemColumnIndex 移动的终止列索引
        /// \param resultItemColumnIndex 移动的目标列索引
        /// \return true-移动成功，false-移动失败
        virtual bool MoveItemsColumnIndex(TableItemIndex startItemColumnIndex, TableItemIndex endItemColumnIndex, TableItemIndex resultItemColumnIndex) = 0;

        /// \brief 设置是否可以被选择
        /// 
        /// \param isSelectable true-可以被选择；false-不可以被选择
        /// \return true 设置成功，false设置失败
        virtual bool SetIsSelectable(bool isSelectable) = 0;

        /// \brief 获取是否可以被选择
        /// 
        /// \return true-可以被选择；false-不可以被选择
        virtual bool IsSelectable() const = 0;

        /// \brief 在表格指定位置插入空行
        ///
        /// 如果oIndex中page小于0则插入失败，如果Row为-1，则会在表格的末尾插入一行，否则按指定位置插入行
        /// \param oIndex 指定行的索引
        /// return true 插入成功, false 插入失败
        GCMP_OBSOLETE_API(2023 / 06 / 01, IDrawingTable::AddRows(const TableItemIndex&, int)) virtual bool AddRow(const TableItemIndex &oIndex) = 0;

        /// \brief 在表格指定位置插入空列
        ///
        /// 如果oIndex中page小于0则插入失败，如果Col为-1，则会在表格的末尾插入一列，否则按指定位置插入列
        /// \param oIndex 指定列的索引
        /// return true 插入成功, false 插入失败
        GCMP_OBSOLETE_API(2023 / 06 / 01, IDrawingTable::AddColumns(const TableItemIndex&, int)) virtual bool AddColumn(const TableItemIndex &oIndex) = 0;

    public:
        /// \brief 创建制定文档视图中创建表格对象
        /// \param pDocument 所属文档
        /// \param pModelView 视图对象
        /// \param bHorizontal 横竖表
        /// \param position 指定位置
        /// \param nRowCount 行数
        /// \param nColumnCount 列数
        /// \param dRowHeight 行高
        /// \param dColumnWidth 列宽
        /// \param elementCreationOption 元素创建选项
        /// \param bDefaultSmartColor 表格默认的样式是否智能反色
        /// \param isChangedWithViewScale 表格是否随视图比例变化
        /// \return 表格Element对象
        static IDrawingTable* Create(IDocument *pDocument, const IModelView *pModelView, bool bHorizontal, Vector3d position, int nRowCount, int nColumnCount, double dRowHeight, double dColumnWidth, ElementCreationOptions elementCreationOption = ElementCreationOptions::Normal, bool bDefaultSmartColor = false, bool isChangedWithViewScale = false);

        /// \brief 获取Implementation Uid
        ///
        /// \return UniIdentity 返回ImplementationUid
        static UniIdentity GetImplementationUid();

        /// \brief 获取表格变化通知事件
        ///
        /// \return 返回获取表格变化通知事件
        static IDrawingTableEvent* GetDrawingTableEvent();
    };
}



